using System;
using Microsoft.Xna.Framework;
using Microsoft.Devices.Sensors;
using Microsoft.Xna.Framework.Input.Touch;

namespace ShootThemUp.Sources.PlayerInputs
{
    /// <summary>
    /// This class determines the player actions and movements in function of the windows phone statement.
    /// The movements are determined by the accelerometer.
    /// The player attacks are determined by the touch screen.
    /// </summary>
    public class WindowsPhonePlayerInput : PlayerInput
    {

        #region Constant Fields

        private const float DEFAULT_ACCELEROMETER_X_VALUE = 0;
        private const float DEFAULT_ACCELEROMETER_Y_VALUE = - 0.5F;

        #endregion

        #region Fields

        private Accelerometer accelerometerSensor;
        private Vector2 accelerometer2DValue = Vector2.Zero;
        private bool accelerometerIsActive = false;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="WindowsPhonePlayerInput"/> class.
        /// </summary>
        public WindowsPhonePlayerInput()
        {
            accelerometerSensor = new Accelerometer();

            // Add the accelerometer event handler to the accelerometer sensor.
            accelerometerSensor.ReadingChanged += new EventHandler<AccelerometerReadingEventArgs>(AccelerometerValuesChanged);

            this.StartAccelerometer();
        }

        #endregion

        #region Methods

        /// <summary>
        /// Starts the accelerometer.
        /// </summary>
        public void StartAccelerometer()
        {
            // Start the accelerometer
            try
            {
                accelerometerSensor.Start();
                accelerometerIsActive = true;
            }
            catch (AccelerometerFailedException)
            {
                // the accelerometer couldn't be started.
                accelerometerIsActive = false;
            }
            catch (UnauthorizedAccessException)
            {
                // This exception is thrown in the emulator-which doesn't support an accelerometer.
                accelerometerIsActive = false;
            }
        }

        /// <summary>
        /// Stops the accelerometer.
        /// </summary>
        public void StopAccelerometer()
        {
            // Stop the accelerometer if it's active.
            if (accelerometerIsActive)
            {
                try
                {
                    accelerometerSensor.Stop();
                    accelerometerIsActive = false;
                }
                catch (AccelerometerFailedException)
                {
                    // the accelerometer couldn't be stopped now.
                }
            }
        }

        #endregion

        #region Inherited Methods

        /// <summary>
        /// Speeds of the player ship, in function of the specified time elapsed and the accelerometer state.
        /// </summary>
        /// <returns>
        /// The new speed of the player, depending of the player inputs.
        /// </returns>
        public override Vector2 Speed()
        {
            return new Vector2(accelerometer2DValue.X - WindowsPhonePlayerInput.DEFAULT_ACCELEROMETER_X_VALUE, - accelerometer2DValue.Y + WindowsPhonePlayerInput.DEFAULT_ACCELEROMETER_Y_VALUE);
        }

        /// <summary>
        /// Determines if the player is shooting, ie if he is pressing the screen.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if the player is shooting; otherwise, <c>false</c>.
        /// </returns>
        public override bool isShooting()
        {
            // Process touch events
            TouchCollection touchCollection = TouchPanel.GetState();
            bool isShooting = false;
            int index = 0;

            while (index < touchCollection.Count && !isShooting)
            {
                if (touchCollection[index].State == TouchLocationState.Pressed)
                    isShooting = true;

                index++;
            }

            return isShooting;
        }

        #endregion

        #region Handlers

        /// <summary>
        /// Handler of the accelerometer events.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">The <see cref="Microsoft.Devices.Sensors.AccelerometerReadingEventArgs"/> instance containing the event data.</param>
        public void AccelerometerValuesChanged(object sender, AccelerometerReadingEventArgs e)
        {
            accelerometer2DValue.X = (float)e.X;
            accelerometer2DValue.Y = (float)e.Y;
        }

        #endregion
    }
}
